//============================================================================================
/**
 * @file	move_pokemon.c
 * @brief	移動ポケモン関連処理
 * @author	Nozomu Saito
 * @date	06.05.11
 */
//============================================================================================
#define	BRANCH_MAX		(6)

#define MOVE_POKE_RAIKOU_LV	(40)
#define MOVE_POKE_ENTEI_LV		(40)

#if  GS_BTS5607_20090723_FIX
#define MOVE_POKE_RATHIASU_LV	(35)
#define MOVE_POKE_RATHIOSU_LV	(35)
#else
#define MOVE_POKE_RATHIASU_LV	(40)
#define MOVE_POKE_RATHIOSU_LV	(40)
#endif

#include "common.h"
#include "fielddata/maptable/zone_id.h"
#include "savedata/encount.h"
#include "savedata/mystatus.h"
#include "poketool/poke_tool.h"
#include "poketool/monsno.h"

#include "move_pokemon_def.h"
#include "move_pokemon.h"

#ifdef PM_DEBUG
#include "field_common.h"
#endif

#include "debug_saito.h"

static void JumpMovePokeLocation(	ENC_SV_PTR data, const u8 inTargetPoke,
									const int inPlayerOldZone);
static void MovePokeLocation(ENC_SV_PTR data, const u8 inTargetPoke, const int inPlayerOldZone);
static void UpdateData(	ENC_SV_PTR data,
						const u8 inTargetPoke,
						const u8  inZoneIdx, const int inZone);
typedef struct MP_LOC_DATA_tag
{
	u16 BranchNum;
	u16 ZoneIdx[BRANCH_MAX];
}MP_LOC_DATA;

static const MP_LOC_DATA MovePokeLocationTbl[LOCATION_MAX] =
{
	//ジョウト
	{2,{1,15,0xffff,0xffff,0xffff,0xffff}},		//0
	{2,{0,2,0xffff,0xffff,0xffff,0xffff}},		//1
	{3,{1,3,7,0xffff,0xffff,0xffff}},			//2
	{3,{2,4,7,0xffff,0xffff,0xffff}},			//3
	{2,{3,5,0xffff,0xffff,0xffff,0xffff}},		//4
	{2,{4,6,0xffff,0xffff,0xffff,0xffff}},		//5
	{2,{5,7,0xffff,0xffff,0xffff,0xffff}},		//6
	{3,{2,3,8,0xffff,0xffff,0xffff}},			//7
	{3,{7,9,11,0xffff,0xffff,0xffff}},			//8
	{3,{8,10,11,0xffff,0xffff,0xffff}},			//9
	{1,{9,0xffff,0xffff,0xffff,0xffff,0xffff}},	//10
	{4,{8,9,12,13,0xffff,0xffff}},				//11
	{2,{11,13,0xffff,0xffff,0xffff,0xffff}},	//12
	{3,{11,12,15,0xffff,0xffff,0xffff}},		//13
	{2,{13,15,0xffff,0xffff,0xffff,0xffff}},	//14
	{2,{0,14,0xffff,0xffff,0xffff,0xffff}},		//15
	//カントー
	{2,{17,37,0xffff,0xffff,0xffff,0xffff}},	//16
	{3,{16,37,18,0xffff,0xffff,0xffff}},		//17
	{2,{17,19,0xffff,0xffff,0xffff,0xffff}},	//18
	{3,{18,20,38,0xffff,0xffff,0xffff}},		//19
	{6,{19,21,22,23,24,38}},					//20
	{3,{22,23,26,0xffff,0xffff,0xffff}},		//21
	{4,{20,21,23,31,0xffff,0xffff}},			//22
	{5,{20,21,22,25,27,0xffff}},				//23
	{4,{19,20,25,38,0xffff,0xffff}},			//24
	{3,{23,24,27,0xffff,0xffff,0xffff}},		//25
	{2,{21,27,0xffff,0xffff,0xffff,0xffff}},	//26
	{4,{23,25,26,28,0xffff,0xffff}},			//27
	{2,{27,29,0xffff,0xffff,0xffff,0xffff}},	//28
	{2,{28,30,0xffff,0xffff,0xffff,0xffff}},	//29
	{3,{29,33,34,0xffff,0xffff,0xffff}},		//30
	{2,{22,37,0xffff,0xffff,0xffff,0xffff}},	//31
	{2,{31,33,0xffff,0xffff,0xffff,0xffff}},	//32
	{3,{30,32,34,0xffff,0xffff,0xffff}},		//33
	{2,{30,33,0xffff,0xffff,0xffff,0xffff}},	//34
	{2,{34,36,0xffff,0xffff,0xffff,0xffff}},	//35
	{2,{16,34,0xffff,0xffff,0xffff}},			//36
	{4,{16,17,39,40,0xffff,0xffff}},			//37
	{3,{19,20,24,0xffff,0xffff,0xffff}},		//38
	{2,{37,40,0xffff,0xffff,0xffff,0xffff}},	//39
	{3,{37,39,24,0xffff,0xffff,0xffff}},		//40
};

static const int ZoneTbl[LOCATION_MAX] = {
	//ジョウト
	ZONE_ID_R29,		//0
	ZONE_ID_R30,		//1
	ZONE_ID_R31,		//2
	ZONE_ID_R32,		//3
	ZONE_ID_R33,		//4
	ZONE_ID_R34,		//5
	ZONE_ID_R35,		//6
	ZONE_ID_R36,		//7
	ZONE_ID_R37,		//8
	ZONE_ID_R38,		//9
	ZONE_ID_R39,		//10
	ZONE_ID_R42,		//11
	ZONE_ID_R43,		//12
	ZONE_ID_R44,		//13
	ZONE_ID_R45,		//14
	ZONE_ID_R46,		//15
	//カントー
	ZONE_ID_R01,		//16
	ZONE_ID_R02,		//17
	ZONE_ID_R03,		//18
	ZONE_ID_R04,		//19
	ZONE_ID_R05,		//20
	ZONE_ID_R06,		//21
	ZONE_ID_R07,		//22
	ZONE_ID_R08,		//23
	ZONE_ID_R09,		//24
	ZONE_ID_R10,		//25
	ZONE_ID_R11,		//26
	ZONE_ID_R12,		//27
	ZONE_ID_R13,		//28
	ZONE_ID_R14,		//29
	ZONE_ID_R15,		//30
	ZONE_ID_R16,		//31
	ZONE_ID_R17,		//32
	ZONE_ID_R18,		//33
	ZONE_ID_W19,		//34
	ZONE_ID_W20,		//35
	ZONE_ID_W21,		//36
	ZONE_ID_R22,		//37
	ZONE_ID_R24,		//38
	ZONE_ID_R26,		//39
	ZONE_ID_R28,		//40
};

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモンジャンプ
 *
 * @param	inEncData		エンカウント関連セーブデータポインタ
 * @param	inTarget		移動対象
 *
 * @return
 */
//--------------------------------------------------------------------------------------------
void MP_JumpMovePokemon(ENC_SV_PTR inEncData, const u8 inTarget)
{
	int player_old_zone;
	player_old_zone = EncDataSave_GetPlayerOldZone(inEncData);
	JumpMovePokeLocation(inEncData, inTarget, player_old_zone);
}

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモン全部ジャンプ
 *
 * @param	inEncData		エンカウント関連セーブデータポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void MP_JumpMovePokemonAll(ENC_SV_PTR inEncData)
{
	u8 i;
	for(i=0;i<MOVE_POKE_MAX;i++){
		//移動中か？
		if ( EncDataSave_IsMovePokeValid(inEncData, i) ){
			//ジャンプ
			MP_JumpMovePokemon(inEncData, i);
		}
	}
}

//-----------------------------------------------------------------------------
/**
 * 移動ポケモンの隣接移動
 *
 * @param	inEncData		エンカウント関連セーブデータポインタ
 *
 * @return	none
 */
//-----------------------------------------------------------------------------
void MP_MovePokemonNeighboring(ENC_SV_PTR inEncData)
{

	u8 i;
	for(i=0;i<MOVE_POKE_MAX;i++){
		//移動中か？
		if ( EncDataSave_IsMovePokeValid(inEncData, i) ){
			//16分の1の確率でジャンプ
			if (gf_p_rand(16) == 0){
				OS_Printf_saitou("%d:ジャンプします\n",i);
				//ジャンプ
				MP_JumpMovePokemon(inEncData, i);

			}else{
				OS_Printf_saitou("%d:隣接移動します\n",i);
				//隣接移動
				{
					int player_old_zone;
					player_old_zone = EncDataSave_GetPlayerOldZone(inEncData);
					MovePokeLocation(inEncData, i, player_old_zone);
				}
			}
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモンゾーン取得
 *
 * @param	inIndex		ゾーンテーブルインデックス
 *
 * @return		int		ゾーンID
 */
//--------------------------------------------------------------------------------------------
int MP_GetMovePokeZone(const u8 inIndex)
{
	GF_ASSERT(inIndex<LOCATION_MAX);
	return ZoneTbl[inIndex];
}

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモンがいるかをチェック
 *
 * @param	inEncData		エンカウント関連セーブデータポインタ
 *
 * @return BOOL		TRUE:いる	FALSE:いない
 */
//--------------------------------------------------------------------------------------------
BOOL MP_CheckMovePoke(ENC_SV_PTR inEncData)
{
	u8 i;
	for(i=0;i<MOVE_POKE_MAX;i++){
		if ( EncDataSave_IsMovePokeValid(inEncData, i) ){
			return TRUE;
		}
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * 主人公ゾーン履歴の更新
 *
 * @param	inEncData		エンカウント関連セーブデータポインタ
 * @param	inZone			更新ゾーン
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void MP_UpdatePlayerZoneHist(ENC_SV_PTR inEncData, const int inZone)
{
	if (MP_CheckMovePoke(inEncData)){
		//履歴更新
		EncDataSave_UpdatePlayerZoneHist( inEncData, inZone );
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 指定移動ポケモンを登録
 *
 * @param	sv					セーブデータ
 * @param	inTargetPoke		対象移動ポケモンインデックス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void MP_AddMovePoke(SAVEDATA *sv, const u8 inTargetPoke)
{
	POKEMON_PARAM *poke_param;
	MPD_PTR	 mpd;
	ENC_SV_PTR data;
	int player_old_zone;
	MYSTATUS * my_st;

	int monsno;
	u8 lv;

	data = EncDataSave_GetSaveDataPtr(sv);
	mpd = EncDataSave_GetMovePokeDataPtr(data, inTargetPoke);

	switch(inTargetPoke){
	case MOVE_POKE_RAIKOU:
		monsno = MONSNO_RAIKOU;
		lv = MOVE_POKE_RAIKOU_LV;
		break;
	case MOVE_POKE_ENTEI:
		monsno = MONSNO_ENTEI;
		lv = MOVE_POKE_ENTEI_LV;
		break;
	case MOVE_POKE_RATHIASU:
		monsno = MONSNO_RATHIASU;
		lv = MOVE_POKE_RATHIASU_LV;
		break;
	case MOVE_POKE_RATHIOSU:
		monsno = MONSNO_RATHIOSU;
		lv = MOVE_POKE_RATHIOSU_LV;
		break;
	default:
		GF_ASSERT(0);
		return ;
	}

	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_MONSNO, monsno);
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_LV, lv);

	my_st =  SaveData_GetMyStatus(sv);

	poke_param = PokemonParam_AllocWork(HEAPID_FIELD);
	PokeParaInit(poke_param);
#ifdef MOVE_POKE_RARE
	PokeParaSet(poke_param, monsno, lv, POW_RND, RND_SET, 0, ID_SET, 0);
#else
	PokeParaSet(poke_param, monsno, lv, POW_RND, RND_NO_SET, 0, ID_SET, MyStatus_GetID_Low(my_st));
#endif

	//状態異常
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_COND, 0);
	//エンカウントフラグ
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_ENC, 1);
	//パワー乱数
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_POW_RND,
											PokeParaGet( poke_param, ID_PARA_power_rnd, NULL ));
	//個性乱数
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_PER_RND,
											PokeParaGet( poke_param, ID_PARA_personal_rnd, NULL ));
	//ＨＰ
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_HP,
											PokeParaGet( poke_param, ID_PARA_hpmax, NULL ));

	sys_FreeMemoryEz(poke_param);

	//初回移動ポケモン出現場所決定
	player_old_zone = EncDataSave_GetPlayerOldZone(data);
	JumpMovePokeLocation(data, inTargetPoke, player_old_zone);
}

//--------------------------------------------------------------------------------------------
/**
 * ポケモンナンバー→移動ポケモン指定IDへの変換
 *
 * @date	2009.06.24
 * @param	monsno	移動ポケモンのポケモンナンバー
 * @return	u8		移動ポケモン指定ID
 */
//--------------------------------------------------------------------------------------------
u8 MP_MonsNoToMovePokeID(u16 monsno)
{
	switch (monsno) {
	case MONSNO_RAIKOU:
		return MOVE_POKE_RAIKOU;
	case MONSNO_ENTEI:
		return MOVE_POKE_ENTEI;
	case MONSNO_RATHIOSU:
		return MOVE_POKE_RATHIOSU;
	case MONSNO_RATHIASU:
		return MOVE_POKE_RATHIASU;
	}
	GF_ASSERT(0);
	return MOVE_POKE_MAX;
}

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモン出現場所抽選
 *
 * @param	data			エンカウント関連セーブデータ
 * @param	inTargetPoke	対象移動ポケモンインデックス
 * @param	inPlayerZone	旧ゾーン
 *
 * @return
 */
//--------------------------------------------------------------------------------------------
static void JumpMovePokeLocation(ENC_SV_PTR data, const u8 inTargetPoke, const int inPlayerOldZone)
{
	u8 zone_idx;
	int move_poke_now_zone;
	int zone;
	u8 max,ofs;
	//主人公が前々回いたゾーンと
	//今自分がいる場所は対象外とする
	move_poke_now_zone = ZoneTbl[EncDataSave_GetMovePokeZoneIdx(data,inTargetPoke)];
	//ジョウト、カントーで分岐
	if ((inTargetPoke == MOVE_POKE_ENTEI)||(inTargetPoke == MOVE_POKE_RAIKOU)){
		max = LOCATION_JOTO_MAX;
		ofs = 0;
	}else{
		max = LOCATION_KANTO_MAX;
		ofs = LOCATION_JOTO_MAX;
	}
	while(1){
		zone_idx = ofs + (gf_rand()%max);
		zone = ZoneTbl[zone_idx];
		if ((zone != inPlayerOldZone)&&(zone != move_poke_now_zone)){
			UpdateData(	data, inTargetPoke, zone_idx, zone);
			OS_Printf_saitou("%dへジャンプ player_old_zone:%d\n",zone,inPlayerOldZone);
			break;
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 移動ポケモン隣接移動
 *
 * @param	data			エンカウント関連セーブデータ
 * @param	inTargetPoke	対象移動ポケモンインデックス
 * @param	inPlayerZone	旧ゾーン
 *
 * @return
 */
//--------------------------------------------------------------------------------------------
static void MovePokeLocation(ENC_SV_PTR data, const u8 inTargetPoke, const int inPlayerOldZone)
{
	const MP_LOC_DATA *loc_data;
	u8 zone_idx;
	int zone;
	loc_data = &(MovePokeLocationTbl[EncDataSave_GetMovePokeZoneIdx(data,inTargetPoke)]);

	if (loc_data->BranchNum == 1){	//変移先が1つしかない場合
		zone_idx = loc_data->ZoneIdx[0];
		zone = ZoneTbl[zone_idx];
		if (zone == inPlayerOldZone){	//主人公の前々回のゾーンだったら、ジャンプ
			OS_Printf_saitou("主人公の旧座標だったのでジャンプに変更\n");
			JumpMovePokeLocation(data, inTargetPoke, inPlayerOldZone);
		}else{
			OS_Printf_saitou("%d:%dに隣接移動\n",inTargetPoke,zone);
			UpdateData(	data, inTargetPoke, zone_idx, zone);
		}
	}else{							//変移先が複数ある場合
		u8 idx;
		while(1){
			//隣接場所をランダムで決定
			idx = gf_p_rand(loc_data->BranchNum);
			zone_idx = loc_data->ZoneIdx[idx];
			zone = ZoneTbl[zone_idx];
			//主人公の前々回いたゾーン以外を選出して移動
			if (zone != inPlayerOldZone){
				OS_Printf_saitou("%d:%dに隣接移動\n",inTargetPoke,zone);
				UpdateData(	data, inTargetPoke, zone_idx, zone);
				break;
			}
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * データ更新
 *
 * @param	data			エンカウント関連セーブデータ
 * @param	inTargetPoke	対象移動ポケモンインデックス
 * @param	inZoneidx		移動ゾーンインデックス
 * @param	inZone			ゾーンＩＤ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void UpdateData(	ENC_SV_PTR data,
						const u8 inTargetPoke,
						const u8  inZoneIdx, const int inZone)
{
	MPD_PTR mpd;
	mpd = EncDataSave_GetMovePokeDataPtr(data, inTargetPoke);
	//更新
	EncDataSave_SetMovePokeZoneIdx(data,inTargetPoke,inZoneIdx);
	//移動ポケモンデータも書き換える
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_ZONE_ID, inZone);
}

#ifdef PM_DEBUG
//--------------------------------------------------------------------------------------------
/**
 * データ更新
 *
 * @param
 *
 * @return
 */
//--------------------------------------------------------------------------------------------
void MP_DebugUpdateData(	ENC_SV_PTR data,
						const u8 inTargetPoke,
						const u8  inZoneIdx)
{
	MPD_PTR mpd;
	mpd = EncDataSave_GetMovePokeDataPtr(data, inTargetPoke);
	//更新
	EncDataSave_SetMovePokeZoneIdx(data,inTargetPoke,inZoneIdx);
	//移動ポケモンデータも書き換える
	EncDataSave_SetMovePokeDataParam(mpd, MP_PARAM_ZONE_ID, ZoneTbl[inZoneIdx]);
}
#endif